package com.jhlishero.study.jdk8.chapter05;

import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

public class Demo5_5_Example01 {

    /**
     * 找出2011年的所有交易，并按交易额排序（从低到高）
     */
    @Test
    public void test01() {
        List<Transaction> transaction2011List = transactionList.stream()
                .filter(transaction -> transaction.getYear() == 2011) //找出2011年所有的交易
                .sorted(Comparator.comparing(Transaction::getValue))  //按交易额从低到高排序
                .collect(Collectors.toList());
        System.out.println(transaction2011List);
    }

    /**
     * 交易员在那些不同的城市工作过
     */
    @Test
    public void test02() {
        //方法一
        List<String> cityList = transactionList.stream()
                .map(transaction -> transaction.getTrader().getCity())
                .distinct()
                .collect(Collectors.toList());
        System.out.println(cityList);

        //方法二
        Set<String> citySet = transactionList.stream()
                .map(transaction -> transaction.getTrader().getCity())
                .collect(Collectors.toSet());
        System.out.println(citySet);
    }

    /**
     * 查找所有来自剑桥的交易员，并按姓名排序
     */
    @Test
    public void test03() {
        List<Trader> traderList = transactionList.stream()
                .map(Transaction::getTrader)
                .filter(trader -> trader.getCity().equals("Cambridge"))
                .distinct()
                .sorted(Comparator.comparing(Trader::getName))
                .collect(Collectors.toList());
        System.out.println(traderList);
    }


    /**
     * 返回所有交易员的姓名字符串，按字母顺序排序
     */
    @Test
    public void test04() {
        String traderNameStr = transactionList.stream()
                .map(transaction -> transaction.getTrader().getName())
                .distinct()
                .sorted()
                .reduce("", (n1, n2) -> n1 + "-" + n2);  //这里使用reduce的效率比较低，因为每次都要新建一个String对象，因此我们可以使用joining方法来代替，joining方法内部使用了StringBuilder

        String traderNameStr02 = transactionList.stream()
                .map(transaction -> transaction.getTrader().getName())
                .distinct()
                .sorted()
                .collect(Collectors.joining("-")); //高效


        System.out.println(traderNameStr);
        System.out.println(traderNameStr02);
    }


    /**
     * 有没有交易员实在米兰工作的
     */
    @Test
    public void test05() {
        boolean milanBased = transactionList.stream().anyMatch(transaction -> transaction.getTrader().getCity().equals("Milan"));
        System.out.println(milanBased);
    }


    /**
     * 打印生活在剑桥的交易员的所有交易额
     */
    @Test
    public void test06() {
        transactionList.stream()
                .filter(transaction -> transaction.getTrader().getCity().equals("Cambridge"))
                .map(Transaction::getValue)
                .forEach(System.out::println);
    }


    /**
     * 交易中，最高交易额
     */
    @Test
    public void test07() {
        Optional<Integer> highestValue = transactionList.stream()
                .map(Transaction::getValue)
                .reduce(Integer::max);
        highestValue.ifPresent(System.out::println);
    }

    /**
     * 交易中最小的交易
     */
    @Test
    public void test08() {
        //方法一
        Optional<Integer> smallestValue = transactionList.stream()
                .map(Transaction::getValue)
                .reduce(Integer::min);
        smallestValue.ifPresent(System.out::println);

        //方法二
        Optional<Transaction> smallestTransaction = null;
        smallestTransaction = transactionList.stream()
                .reduce((t1, t2) -> t1.getValue() < t2.getValue() ? t1 : t2);
        smallestTransaction.ifPresent(System.out::println);

        //方法三
        smallestTransaction = transactionList.stream().min(Comparator.comparing(Transaction::getValue));
        smallestTransaction.ifPresent(System.out::println);
    }



    Trader raoul = new Trader("Raoul", "Cambridge");
    Trader mario = new Trader("Mario", "Milan");
    Trader alan = new Trader("Alan", "Cambridge");
    Trader brain = new Trader("Brain", "Cambridge");

    List<Transaction> transactionList = Arrays.asList(
      new Transaction(brain, 2011, 300),
      new Transaction(raoul, 2012, 1000),
      new Transaction(raoul, 2011, 400),
      new Transaction(mario, 2012, 710),
      new Transaction(mario, 2012, 700),
      new Transaction(alan, 2012, 950)
    );

    class Trader {
        private final String name;
        private final String city;

        public Trader(String n, String c) {
            this.name = n;
            this.city = c;
        }

        public String getName() {
            return name;
        }

        public String getCity() {
            return city;
        }

        @Override
        public String toString() {
            return "Trader{" +
                    "name='" + name + '\'' +
                    ", city='" + city + '\'' +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Trader trader = (Trader) o;
            return Objects.equals(name, trader.name) &&
                    Objects.equals(city, trader.city);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, city);
        }
    }

    class Transaction {
        private final Trader trader;
        private final int year;
        private final int value;

        public Transaction(Trader trader, int year, int value) {
            this.trader = trader;
            this.year = year;
            this.value = value;
        }

        public Trader getTrader() {
            return trader;
        }

        public int getYear() {
            return year;
        }

        public int getValue() {
            return value;
        }

        @Override
        public String toString() {
            return "Transaction{" +
                    "trader=" + trader +
                    ", year=" + year +
                    ", value=" + value +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Transaction that = (Transaction) o;
            return year == that.year &&
                    value == that.value &&
                    Objects.equals(trader, that.trader);
        }

        @Override
        public int hashCode() {
            return Objects.hash(trader, year, value);
        }
    }
}
